package javase.ch03.homeWork.Test2;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 面试题 - 常见阻塞队列：用来保存等待执行任务的队列
 * 1.ArrayBlockingQueue     基于数组结构的有界阻塞队列,按FIFO排序任务
 * 2.LinkedBlockingQueue    基于链表结构的阻塞队列，按FIFO排序任务。吞吐量通常要高于ArrayBlockingQueue
 * 3.SynchronousQueue       一个不存储元素的阻塞队列，每个插入操作必须等到另一个线程调用移除操作，否则插入操作一直处于阻塞状态，吞吐量通常要高于LinkedBlockingQueue
 * 4.PriorityBlockingQueue  具有优先级的无界阻塞队列
 *
 * 面试题 - 自定义线程池的拒绝策略
 * 1.AbortPolicy   直接拒绝任务，并抛出异常RejectedExecutionException的策略
 * 2.DiscardPolicy 直接拒绝任务，但是不抛出异常
 * 3.DiscardOldestPolicy  拒绝任务队列中排队最久的任务，将新的任务加入至队列的末尾
 * 4.CallerRunsPolicy  调起正在执行当前任务的的线程来执行
 *
 */
public class CustomThreadPoolDemo1 {

    public static void main(String[] args) {
        //创建线程池
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                2, 3 ,
                60L , TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(2),
                new ThreadPoolExecutor.DiscardOldestPolicy()
        );

        //执行任务
        /**
         * 拒绝策略  以DiscardOldestPolicy为例
         * 1.由corePoolSize执行
         * 2.由corePoolSize执行
         * 3.进入阻塞队列  queue
         * 4.进入阻塞队列  queue
         * 5.计算目前能够创建线程的个数 maxPoolSize - corePoolSize=1 创建新的线程执行任务
         * 6.根据拒绝策略进行执行 ， DiscardOldestPolicy策略 ， 将第三个线任务丢掉，把第六个任务放进去
         */
        for (int i = 1; i <=6 ; i++) {
            pool.execute(new MyRun("i = "+i));
        }


        //查看阻塞队列中的任务信息
        BlockingQueue<Runnable> queue = pool.getQueue();
        for (Runnable runnable : queue) {
            System.out.println(runnable);
        }

        //关闭线程池
        pool.shutdown();
    }

}
class MyRun implements Runnable{

    private String name;

    public MyRun(String name){
        this.name = name;
    }

    @Override
    public void run() {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(Thread.currentThread().getName()+",执行的任务是："+name);
    }

    @Override
    public String toString() {
        return "MyRun{" +
                "name='" + name + '\'' +
                '}';
    }
}